package jpa;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import jpa.entities.Employee;
import jpa.entities.Project;

/**
 * @author Remco Haszing
 */
public class JPAConnection {

    // properties
    private EntityManager em;

    // constructor
    /**
     * Allows communication with the database using a JPA connection. This
     * constructor creates an EntityManager using an EntityManagerFactory that
     * uses a persistance unit with the given name.
     *
     * @param persistanceUnit The name of the persistance unit to use.
     */
    public JPAConnection(String persistanceUnit) {
        this.em = Persistence.createEntityManagerFactory(persistanceUnit).createEntityManager();
    }

    // methods
    /**
     * Adds the object to the database. This method inserts the object into the
     * database. If such a table does not exist, it is being created
     * automatically.
     *
     * @param object The object to be added to the database.
     */
    public void create(Object object) {
        this.em.getTransaction().begin();
        this.em.persist(object);
        this.em.getTransaction().commit();
    }

    /**
     * Merges the objects altered properties with the database. This method
     * merges the object properties with those in the database.
     *
     * @param object The object to be merged with the database.
     */
    public void edit(Object object) {
        this.em.getTransaction().begin();
        this.em.merge(object);
        this.em.getTransaction().commit();
    }

    /**
     * Completely removes an object from the database. This method removes an
     * object and all it's records from the database.
     *
     * @param object The object to be removed.
     */
    public void remove(Object object) {
        this.em.getTransaction().begin();
        this.em.remove(this.em.merge(object));
        this.em.getTransaction().commit();
    }

    /**
     * Returns an employee from the database if it matches the given username
     * and password. This method checks if an employee with the given username
     * and password exists and if so it returns it. If such an employee does not
     * exist it will return null.
     *
     * @param username The username of the employee.
     * @param password The password of the employee.
     * @return The employee matching the given username and password.
     */
    public Employee getUserByUsername(String username, String password) {
        try {
            this.em.getTransaction().begin();
            Query q = this.em.createNamedQuery("Employee.findByUsername", Employee.class);
            this.em.getTransaction().commit();
            q.setParameter("username", username);
            q.setParameter("password", Employee.sha1(password));
            return (Employee) q.getSingleResult();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * @return A list containing all users.
     */
    public List<Employee> getAllUsers() {
        CriteriaQuery cq = this.em.getCriteriaBuilder().createQuery();
        cq.select(cq.from(Employee.class));
        return this.em.createQuery(cq).getResultList();
    }

    /**
     * @return A list containing all projects.
     */
    public List<Project> getAllProjects() {
        CriteriaQuery cq = this.em.getCriteriaBuilder().createQuery();
        cq.select(cq.from(Project.class));
        return this.em.createQuery(cq).getResultList();
    }
}
